﻿using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System;

namespace DatabaseManager.Core.Models
{
    public class GlobalMetadataRepository
    {
        //private readonly List<DatabaseMetadata> _metadataList = new();
        //private readonly ConcurrentDictionary<string, List<ColumnInfo>> _columnCache = new();
        //private readonly Dictionary<string, HashSet<string>> _invertedIndex = new();
        
        private readonly List<DatabaseMetadata> _metadataList = new List<DatabaseMetadata>();
        private readonly ConcurrentDictionary<string, List<ColumnInfo>> _columnCache = new ConcurrentDictionary<string, List<ColumnInfo>>();
        private readonly Dictionary<string, HashSet<string>> _invertedIndex = new Dictionary<string, HashSet<string>>();
       
        public void AddMetadata(string dbKey, DatabaseMetadata metadata)
        {
            _metadataList.Add(metadata);
            UpdateCache(dbKey, metadata);
            UpdateInvertedIndex(metadata);
        }

        private void UpdateCache(string dbKey, DatabaseMetadata metadata)
        {
            var columns = metadata.GetAllColumns().ToList();
            _columnCache.AddOrUpdate(dbKey, columns, (key, old) => columns);
        }

        private void UpdateInvertedIndex(DatabaseMetadata metadata)
        {
            var allColumns = metadata.GetAllColumns();
            foreach (var column in allColumns)
            {
                var keywords = ExtractKeywords(column.Name + " " + column.Comment);
                foreach (var keyword in keywords)
                {
                    if (!_invertedIndex.ContainsKey(keyword))
                    {
                        _invertedIndex[keyword] = new HashSet<string>();
                    }

                    _invertedIndex[keyword].Add($"{column.TableName}.{column.Name}");
                }
            }
        }

        public IEnumerable<ColumnInfo> GetAllColumnsAcrossDatabases()
        {
            return _columnCache.Values.SelectMany(c => c);
        }

        public IEnumerable<string> SearchColumns(string keyword)
        {
            keyword = keyword.ToLower();
            if (_invertedIndex.TryGetValue(keyword, out var results))
            {
                return results;
            }
            return Enumerable.Empty<string>();
        }

        private IEnumerable<string> ExtractKeywords(string text)
        {
            if (string.IsNullOrWhiteSpace(text)) yield break;

            var words = text.ToLower()
                            .Split(new[] { ' ', '.', '_', '-', ',', ';', ':', '(', ')', '[', ']' },
                                   StringSplitOptions.RemoveEmptyEntries);

            foreach (var word in words.Distinct())
            {
                yield return word;
            }
        }
    }
}
